package engine;

import java.util.ArrayList;

public class Memory extends MemoryHierarchy{
	
	private int size;
	private int type;
	public ArrayList<String> memory;
	private int accessTime;
	private int L;
	public Memory (int _size,int _L,int _accessTime){
		this.size = _size;
		this.accessTime = _accessTime;
		this.L = _L;
		String word = "0";
		memory = new ArrayList<String>(size);
		for(int i = 0;i<size;i++){
			memory.add(word);
		}
	}
	public int ones(int num) {
		int result = 0;
		for (int i = 0; i < num; i++) {
			result = result << 1;
			result++;

		}
		return result;
	}

	static int log(int x, int base) {
		return (int) (Math.log(x) / Math.log(base));
	}

	
	public ArrayList<String> read(int address) {
		latency +=accessTime;
		int offset = address & (ones(log(L, 2)));;
		address-=offset;
		return LoadBlock(address);
	}
	
	
	
	public ArrayList<String> write(int address,String word) {
		ArrayList<String> block = read(address);
		int offset = address & (ones(log(L, 2)));
		block.set(offset, word);
		writeBlock(address,block);
		latency -=accessTime;
		return block;
	}
	
	public ArrayList<String> virtualWrite(int address,String word) {
		latency -=accessTime;
		ArrayList<String> block = read(address);
		int offset = address & (ones(log(L, 2)));
		block.set(offset, word);
		//writeBlock(address,block);
		return block;
	}
	
	public String LoadWord(int address){
		return memory.get(address);
	}
	
	public void StoreWord(int address,String word){
		memory.set(address, word);
	}
	
	public ArrayList<String> LoadBlock(int address){
		ArrayList<String> block = new ArrayList<String>();
		for(int i = 0;i<L;i++){
			block.add(memory.get(address++));
		}
		return block;
	}
	
	public void writeBlock(int address,ArrayList<String> block){
		int offset = address & (ones(log(L, 2)));
		latency +=accessTime;
		for(int i = 0;i<L;i++){
			memory.set(address-offset+i,block.get(i));
		}
	}

	public static void main(String[]args){
		Memory m = new Memory(16,4,70);
		m.StoreWord(0, "mina");
		m.StoreWord(1, "mina");
		m.StoreWord(2, "mina");
		m.StoreWord(3, "mina");
		m.StoreWord(4, "fina");
		m.StoreWord(5, "fina");
		System.out.println(m.read(4));
		ArrayList<String> arr = new ArrayList<String>();
		arr.add("lol");
		arr.add("lol");
		arr.add("lol");
		arr.add("lol");
		m.writeBlock(4,arr);
		System.out.println(m.read(4));
	}
}
